package itheima.entry;

import itheima.domain.Card;
import itheima.service.MetroService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class ServiceEntry {
    private static final Logger LOGGER = LoggerFactory.getLogger(ServiceEntry.class);
    private static MetroService ms = new MetroService();

    public static void main(String[] args) throws IOException {
        //1.创建线程池
        ThreadPoolExecutor pool = new ThreadPoolExecutor(5,8,10,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(10),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());

        //2.服务器
        ServerSocket ss = new ServerSocket(10002);

        //3.创建线程处理
        while (true){
            LOGGER.info("服务器开始接收数据");
            Socket socket = ss.accept();
            LOGGER.info("服务器已经接收到数据，开始执行");

            pool.submit(()->{
                try {
                    BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                    String clientData = br.readLine();

                    String option = clientData.split("&")[0];
                    String data = clientData.split("&")[1];

                    switch (option){
                        case "ID_FIND":
                            LOGGER.debug("执行ID_FIND");
                            isExist(data,socket);
                            break;
                        case "ADD_USER":
                            LOGGER.debug("执行ADD_USER");
                            addUser(data,socket);
                            break;
                        case "GET_USERNAME":
                            LOGGER.debug("执行GET_USERNAME");
                            getUsername(data,socket);
                            break;
                        case "GET_STATIONS":
                            LOGGER.debug("执行GET_STATIONS");
                            getStations(socket);
                            break;
                        case "BUY_TICKET":
                            LOGGER.debug("执行BUY_TICKET");
                            buyTicket(data,socket);
                            break;
                        case "VERIFY_USER":
                            LOGGER.debug("VERIFY_USER");
                            verifyUser(data,socket);
                            break;
                        case "GET_USERNAME_MONEY":
                            LOGGER.debug("GET_USERNAME_MONEY");
                            getUsername_Money(data,socket);
                            break;
                        case "CHARGE_MONEY":
                            LOGGER.debug("CHARGE_MONEY");
                            charge(data,socket);
                            break;
                        case "SAVE_USERLOG":
                            LOGGER.debug("SAVE_USERLOG");
                            saveUserLog(data,socket);
                            break;
                        default:
                            LOGGER.debug("您的输入有误");
                            break;
                    }

                } catch (IOException e) {
                    e.printStackTrace();
                }

            });

        }
    }

    private static void saveUserLog(String data, Socket socket) throws IOException {
        ms.saveUserLog(data);
        socket.close();
    }

    private static void charge(String data, Socket socket) throws IOException {
        String cardId = data.split(",")[0];
        String moneyStr = data.split(",")[1];
        double money = Double.parseDouble(moneyStr);

        boolean flag = ms.charge(cardId,money);
        String message = flag+"";
        BufferedWriter bw =new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        bw.write(message);
        bw.flush();

        bw.close();
        socket.close();
    }

    private static void getUsername_Money(String data, Socket socket) throws IOException {
        String username = ms.getUsername(data);
        double money = ms.giveMoney(data);

        String message = username+","+money;
        BufferedWriter bw =new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        bw.write(message);
        bw.flush();

        bw.close();
        socket.close();
    }

    private static void verifyUser(String data, Socket socket) throws IOException {
        String cardId = data.split(",")[0];
        String xing = data.split(",")[1];

        boolean flag = ms.verify(cardId,xing);
        //向客户端返回信息
        String message = flag+"";
        BufferedWriter bw =new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        bw.write(message);
        bw.flush();

        bw.close();
        socket.close();
    }

    private static void buyTicket(String data, Socket socket) throws IOException {
        //记录卖票数据，同时返回买票者信息以及余额
        String cardId = data.split(",")[0];
        String startStation = data.split(",")[1];
        String endStation = data.split(",")[2];
        String money = ms.buyTicket(cardId,startStation,endStation);
        String username = ms.getUsername(cardId);

        BufferedWriter bw =new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        bw.write(username+"&"+money);
        bw.flush();

        bw.close();
        socket.close();
    }

    private static void getStations(Socket socket) throws IOException {
        ArrayList<String> list = ms.getStations();

        ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
        oos.writeObject(list);
        oos.flush();
        oos.close();
        socket.close();
    }

    private static void getUsername(String data, Socket socket) throws IOException {
        String username = ms.getUsername(data);

        //返回查询结果
        BufferedWriter bw =new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        bw.write(username);
        bw.flush();

        bw.close();
        socket.close();
    }

    private static void addUser(String data, Socket socket) throws IOException {
        String username = data.split(",")[0];
        String cardId = data.split(",")[1];
        String moneyStr = data.split(",")[2];
        double money = Double.parseDouble(moneyStr);

        Card card = new Card(username,cardId,money);
        boolean flag = ms.addUser(card);

        //向客户端返回信息
        String message = flag+"";
        BufferedWriter bw =new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        bw.write(message);
        bw.flush();

        bw.close();
        socket.close();
    }

    private static void isExist(String data, Socket socket) throws IOException {
        MetroService ms = new MetroService();
        //调用Service确认id是否存在
        int index = ms.isExist(data);
        String s = "true";
        if(index == -1){
            s = "false";
        }
        //返回查询结果
        BufferedWriter bw =new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        bw.write(s);
        bw.flush();
        bw.close();
        socket.close();
    }
}
